package service

import (
	"fmt"
	"os/exec"
	"sync"
	"time"

	"github.com/uber-go/zap"
)

// 监督已经启动的应用的状态，一旦应用不再存活，立即重启应用

var wg1 = sync.WaitGroup{}

func startSupervisor() {
	// 监督通过自动下载启动的应用
	go func() {
		time.Sleep(20 * time.Second)
		for {
			defer func() {
				if err := recover(); err != nil {
					Logger.Error("supervisor error", zap.Error(err.(error)), zap.Stack())
				}
			}()

			for _, app := range AppMap {
				go func(app *App) {
					wg1.Add(1)
					defer wg1.Done()

					if app.needStarted {
						if app.appType == "none" {
							return
						}
						// 检查app的存活状态
						var cmd *exec.Cmd
						c := fmt.Sprintf("ps -ef | grep %s | grep -v 'grep ' | awk '{print $2}'", app.Name)
						cmd = exec.Command("/bin/sh", "-c", c)

						bs, err := cmd.CombinedOutput()
						if err != nil || string(bs) == "" {

							//服务挂了，需要重启
							// 获取上一条报错日志
							// cmd = exec.Command("/bin/sh", "-c", "tail -50 "+app.logDir+"/error.log")
							// bs, _ := cmd.CombinedOutput()

							// app.LastErrorLog = talents.Bytes2String(bs)
							// fmt.Println(app.LastErrorLog)
							stopApp(app, 1*time.Second)
							err := startApp(app, Conf.Client.AppStartWait)
							if err != nil {
								Logger.Info("应用重启失败", zap.String("app", app.Name))
							} else {
								Logger.Info("应用重启成功", zap.String("app", app.Name))
							}

							app.RestartTimes++

						}
					} else if !app.needStarted && app.IsStarted {
						// 若App无需启动，且APp处于启动状态，则关闭app
						stopApp(app, 1*time.Second)
						Logger.Info("停止应用", zap.String("app", app.Name))
					}
				}(app)
			}

			time.Sleep(100 * time.Millisecond)

			wg1.Wait()
			time.Sleep(Conf.Client.SupervisorInterval)
		}
	}()

	//监督指定的应用存活
	go func() {
		for {
			defer func() {
				if err := recover(); err != nil {
					Logger.Error("deamon error", zap.Error(err.(error)), zap.Stack())
				}
			}()

			for _, d := range DaemonMap {
				var cmd *exec.Cmd
				c := fmt.Sprintf("ps -ef | grep %s | grep -v 'grep ' | awk '{print $2}'", d.Name)
				cmd = exec.Command("/bin/sh", "-c", c)

				bs, err := cmd.CombinedOutput()
				if err != nil || string(bs) == "" {
					cmd := exec.Command("/bin/sh", "-c", d.StartCmd)
					cmd.Dir = d.StartDir
					bs, err := cmd.CombinedOutput()
					if err != nil {
						Logger.Warn("start daemon error",
							zap.String("name", d.Name), zap.Error(err), zap.String("stdout", string(bs)), zap.String("cmd", d.StartCmd))
						// 启动失败，说明存在严重bug，重新下载

						continue
					}
				}

				c = fmt.Sprintf("ps -ef | grep %s | grep -v 'grep ' | awk '{print $2}'", d.Name)
				cmd = exec.Command("/bin/sh", "-c", c)

				bs, err = cmd.CombinedOutput()
				if err != nil || string(bs) == "" {
					Logger.Warn("daemon启动失败", zap.Error(err), zap.String("stdout", string(bs)))
				}
			}

			time.Sleep(Conf.Client.SupervisorInterval)
		}
	}()

	// 执行定时任务
	// 例如定时停止应用，再启动应用
	go func() {
		for _, d := range TimerMap {
			go func(d *Timer) {
				defer func() {
					if err := recover(); err != nil {
						Logger.Error("timer error", zap.Error(err.(error)), zap.Stack())
					}
				}()

				for {
					var cs string
					//启动时先杀死应用
					if d.StopCmd == "default" {
						c := fmt.Sprintf("kill `ps -ef | grep %s | grep -v 'grep ' | awk '{print $2}'`", d.Name)
						cmd := exec.Command("/bin/sh", "-c", c)
						cmd.CombinedOutput()

						time.Sleep(Conf.Client.AppStopWait)

						c = fmt.Sprintf("kill -9 `ps -ef | grep %s | grep -v 'grep ' | awk '{print $2}'`", d.Name)
						cmd = exec.Command("/bin/sh", "-c", c)
						cmd.CombinedOutput()
					} else {
						cmd := exec.Command("/bin/sh", "-c", d.StopCmd)
						cmd.CombinedOutput()
						time.Sleep(Conf.Client.AppStopWait)
					}

					//启动应用
					cmd := exec.Command("/bin/sh", "-c", d.StartCmd)
					cmd.Dir = d.StartDir
					bs, err := cmd.CombinedOutput()
					if err != nil {
						Logger.Warn("start daemon error",
							zap.String("name", d.Name), zap.Error(err), zap.String("stdout", string(bs)), zap.String("cmd", d.StartCmd))
						// 启动失败，说明存在严重bug，重新下载
						goto PAUSE
					}

					time.Sleep(Conf.Client.AppStartWait)

					cs = fmt.Sprintf("ps -ef | grep %s | grep -v 'grep ' | awk '{print $2}'", d.Name)
					cmd = exec.Command("/bin/sh", "-c", cs)

					bs, err = cmd.CombinedOutput()
					if err != nil || string(bs) == "" {
						Logger.Warn("timer启动失败", zap.Error(err), zap.String("stdout", string(bs)))
					}

					// 暂停一定时间，再循环
				PAUSE:
					Logger.Debug("timer启动成功", zap.Object("app", d))
					time.Sleep(d.Interval)
				}

			}(d)

		}
	}()

}
